#pragma once

#include "rewine/IImage.hpp"

#include <list>
#include <string>
#include <string_view>
#include <memory>

namespace rewine
{

enum class LoadState : int {
    Unloaded    = 0,
    Loading     = 1,
    Loaded      = 2,
    Failed      = -1,
};

class CImage : public IImage {
private:

    std::string m_Fullname;
    std::string m_ExportName;
    std::string_view m_ModuleName;

    LoadState m_LoadState = LoadState::Unloaded;
    int m_LastError = 0;

    using importing_list_t = std::list<std::shared_ptr<IImage>>;
    using imported_list_t = std::list<std::weak_ptr<IImage>>;

    std::weak_ptr<IImage>   m_wpSelf;
    bool                    m_bPinned = false;
    importing_list_t        m_Importing;
    imported_list_t         m_ImportedBy;

public:

    CImage() = default;
    ~CImage() override = default;

protected:

    bool setExportName(const std::string& exportName);

    void setIsUnloaded() {
        m_LoadState = LoadState::Unloaded;
    }

    void setIsLoading() {
        m_LoadState = LoadState::Loading;
    }

    void setIsLoaded(bool bSuccess) {
        m_LoadState = bSuccess ? LoadState::Loaded : LoadState::Failed;
    }

    void setLastError(int iValue) {
        m_LastError = iValue;
    }

public:

    void setFullName(const std::string& fullname) {
        m_Fullname = fullname;
    }

public:

    std::string fullname() const override {
        return m_Fullname;
    }

    std::string exportName() const override {
        return m_ExportName;
    }

    std::string moduleName() const override {
        return std::string(m_ModuleName);
    }

    bool isInitialized() const override {
        return !m_Fullname.empty();
    }

    bool isParsed() const override {
        return !m_ExportName.empty();
    }

    bool isLoading() const {
        return m_LoadState == LoadState::Loading;
    }

    bool isLoaded() const override {
        return m_LoadState == LoadState::Loaded;
    }

    bool isFailed() const override {
        return m_LoadState == LoadState::Failed;
    }

    int getLastError() const override {
        return m_LastError;
    }

    void setSelf(const std::shared_ptr<IImage>& spImage) override {
        m_wpSelf = spImage;
    }

    std::shared_ptr<IImage> getSelf() override {
        return m_wpSelf.lock();
    }

    void setPinned(bool bValue) override {
        m_bPinned = bValue;
    }

    bool isPinned() const override {
        return m_bPinned;
    }

    bool checkActivity() override;

    void setImport(const std::shared_ptr<IImage>& spImported) override {
        m_Importing.emplace_back(spImported);
        spImported->onImported(getSelf());
    }

    void onImported(const std::shared_ptr<IImage>& spImporter) override {
        m_ImportedBy.emplace_back(std::weak_ptr<IImage>(spImporter));
    }

    BOOL onEvent(DWORD dwReason) const override {
        return TRUE;
    }

};

} // namespace rewine
